/* ****************************************************************** **
**    OpenSees - Open System for Earthquake Engineering Simulation    **
**          Pacific Earthquake Engineering Research Center            **
** ****************************************************************** */

//
// 文件: GPUMaterialKernels.h
// 创建时间: 2025年10月3日
// 说明: GPU材料本构核函数声明
// 作者: OpenSees GPU加速项目组
//
// 功能:
//   - 定义GPU材料参数结构
//   - 声明各种材料的GPU本构算法
//   - 支持非线性材料（塑性、硬化等）
//

#ifndef GPUMaterialKernels_h
#define GPUMaterialKernels_h

#include <cuda_runtime.h>
#include "GPUElementSupport.h"  // 使用统一的GPUMaterialType枚举定义

//==============================================================================
// 注意：GPUMaterialType枚举已在GPUElementSupport.h中定义
//==============================================================================

//==============================================================================
// GPU材料参数结构
//==============================================================================

/**
 * @brief Drucker-Prager材料参数
 *
 * 屈服面: f = sqrt(J2) + alpha * I1 - k
 * 流动法则: g = sqrt(J2) + beta * I1 (非关联流动)
 * 硬化: k = k0 + (kinf - k0) * (1 - exp(-delta * alpha_p))
 */
struct DruckerPragerParams {
    // 弹性参数
    double K;              // 体积模量
    double G;              // 剪切模量

    // 屈服参数
    double sigma_y;        // 初始屈服应力
    double rho;            // 摩擦参数 alpha = 2*sin(phi) / sqrt(3*(3-sin(phi)))
    double rho_bar;        // 膨胀参数 beta (非关联流动)

    // 硬化参数
    double Kinf;           // 最终硬化模量
    double Ko;             // 初始硬化模量
    double delta1;         // 硬化指数参数（DP面）
    double delta2;         // 硬化指数参数（拉伸截断面）
    double Hard;           // 线性硬化模量
    double theta;          // 积分参数

    // 其他参数
    double Patm;           // 大气压力参考值
    double massDen;        // 质量密度
};

/**
 * @brief 弹性各向同性材料参数
 */
struct ElasticIsotropicParams {
    double E;              // 弹性模量
    double nu;             // 泊松比
    double rho;            // 密度
};

/**
 * @brief J2塑性材料参数
 */
struct J2PlasticityParams {
    double K;              // 体积模量
    double G;              // 剪切模量
    double sigma_y;        // 屈服应力
    double Hiso;           // 等向硬化模量
    double Hkin;           // 运动硬化模量
};

/**
 * @brief GPU材料状态变量
 * 存储每个积分点的历史变量
 */
struct MaterialState {
    // 应力（6个分量：σxx, σyy, σzz, σxy, σyz, σzx）
    double stress[6];

    // 塑性应变（6个分量）
    double plasticStrain[6];

    // 硬化变量
    double alpha;          // 累积塑性应变
    double backstress[6];  // 背应力（运动硬化）

    // 其他状态变量
    double stateVars[8];   // 材料特定的状态变量
};

//==============================================================================
// GPU材料本构算法声明
//==============================================================================
// 注意：CUDA设备函数不需要extern "C"，因为使用C++引用参数

/**
 * @brief Drucker-Prager材料应力更新（GPU kernel）
 *
 * @param strain_increment 应变增量（6个分量）
 * @param params 材料参数
 * @param state 材料状态（输入输出）
 * @param stress 输出应力
 * @param D_tangent 输出切线刚度矩阵（6x6，存储为36个元素）
 */
__device__ void computeDruckerPragerStress(
    const double* strain_increment,
    const DruckerPragerParams& params,
    MaterialState& state,
    double* stress,
    double* D_tangent
);

/**
 * @brief 弹性各向同性材料应力更新
 */
__device__ void computeElasticIsotropicStress(
    const double* strain,
    const ElasticIsotropicParams& params,
    double* stress,
    double* D_tangent
);

/**
 * @brief J2塑性材料应力更新
 */
__device__ void computeJ2PlasticityStress(
    const double* strain_increment,
    const J2PlasticityParams& params,
    MaterialState& state,
    double* stress,
    double* D_tangent
);

/**
 * @brief 材料类型调度器
 * 根据材料类型调用对应的本构算法
 */
__device__ void computeMaterialStress(
    GPUMaterialType matType,
    const double* strain_increment,
    const void* params,
    MaterialState& state,
    double* stress,
    double* D_tangent
);

//==============================================================================
// 辅助设备函数
//==============================================================================

/**
 * @brief 计算应力不变量
 * @param stress 应力分量（6个）
 * @param I1 第一不变量（平均应力 * 3）
 * @param J2 第二偏应力不变量
 */
__device__ void computeStressInvariants(
    const double* stress,
    double& I1,
    double& J2
);

/**
 * @brief 计算弹性刚度矩阵
 */
__device__ void computeElasticD(
    double K,
    double G,
    double* D
);

#endif // GPUMaterialKernels_h
